 ///
 /// @file    typeCast1.cc
 /// @author  lemon(haohb13@gmail.com)
 /// @date    2023-04-28 10:19:24
 ///
 
#include <iostream>
using std::cout;
using std::endl;


class Complex
{
public:
	Complex(double dreal = 0, double dimage = 0)
	: _dreal(dreal)
	, _dimage(dimage)
	{	cout << "Complex(double,double)" << endl;}

	friend std::ostream & operator<<(std::ostream & os, const Complex & rhs);
	friend class Point;

private:
	double _dreal;
	double _dimage;
};

std::ostream & operator<<(std::ostream & os, const Complex & rhs)
{
	os << rhs._dreal;
	if(rhs._dimage > 0) {
		os << " + " << rhs._dimage << "i" << endl;
	} else if(rhs._dimage == 0){
		return os;
	} else {
		os << " - " <<  rhs._dimage * ( -1 )  << "i" << endl;
	}
	return os;
}

class Point
{
public:
	//有可能发生隐式转换的情况是只有一个参数的构造函数
	//不希望隐式转换发生
	//explicit
	Point(int ix)
	: _ix(ix)
	, _iy(0)
	{	cout << "Point(int)" << endl;	}

	Point(const Point & rhs)
	: _ix(rhs._ix)
	, _iy(rhs._iy)
	{	cout << "Point(const Point&)" << endl;}

	Point & operator=(const Point & rhs)
	{
		cout << "Point & operator=(const Point&)" << endl;
		_ix = rhs._ix;
		_iy = rhs._iy;
		return *this;
	}

	Point(int ix, int iy)
	: _ix(ix)
	, _iy(iy)
	{	cout << "Point(int,int)" << endl;}

	friend std::ostream & operator<<(std::ostream & os, const Point & rhs);

	~Point() {	cout << "~Point()" << endl;	}

	//类型转换函数, 将一个自定义类类型转换为其他类型
	//可以进行重载, 虽然功能很强大，但是一般情况下，不推荐使用
	operator int()
	{	
		cout << "operator int()" << endl;
		return _ix;	
	}

	operator double()
	{	
		cout << "operator double()" << endl;
		return 1.1 * _ix * _iy;	
	}

	operator Complex()
	{
		cout << "operator Complex()" << endl;
		return Complex(_ix, _iy);
	}

private:
	int _ix;
	int _iy;
};
	
std::ostream & operator<<(std::ostream & os, const Point & rhs)
{
	os << "(" << rhs._ix
	   << "," << rhs._iy
	   << ")";
	return os;
}
 
void test0() 
{
	//Point pt = 1;// 1 ==> Point(1, 0) ==> pt 隐式转换
	Point pt(12, 2);
	cout << "pt:" << pt << endl;

	int x = pt;
	double y = pt;
	Complex c1 = pt;
	cout << "x:" << x << endl;
	cout << "y:" << y << endl;
	cout << "c1:" << c1 << endl;
 
} 
 
int main(void)
{
	test0();
	return 0;
}
